﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using CTS.Com.Domain.Constants;
using CTS.Com.Domain.Model;

namespace CTS.Com.Domain.Helper
{
    public static class DataHelper
    {
        /***** Xóa [#1] đầu *****/
        ///// <summary>
        ///// Join string array with delimiter
        ///// </summary>
        ///// <param name="data">Array string</param>
        ///// <param name="delimiter">delimiter</param>
        ///// <returns>String</returns>
        //public static string JoinStringArray(string[] data, string delimiter)
        //{
        //    var result = new StringBuilder();
        //    foreach (var s in data) {
        //        if (!DataCheckHelper.IsNull(result.ToString())) {
        //            result.Append(delimiter);
        //        }
        //
        //        result.Append(s);
        //    }
        //    return result.ToString();
        //}
        /***** Xóa [#1] cuối *****/

        /***** Thêm [#1] đầu *****/
        /// <summary>
        /// Nối danh sách đối tượng với dấu phân cách 
        /// </summary>
        /// <param name="data">Danh sách đối tượng</param>
        /// <param name="delimiter">Dấu phân cách</param>
        /// <returns>Chuỗi nối</returns>
        public static string JoinStringList(IList data, string delimiter)
        {
            // Khởi tạo biến cục bộ
            var result = new StringBuilder();
            // Diệt chuỗi trong mảng chuỗi
            foreach (var s in data) {
                // Thêm dấu phân tách
                if (!DataCheckHelper.IsNull(result.ToString())) {
                    result.Append(delimiter);
                }
                // Nỗi chuỗi
                result.Append(s.ToString());
            }
            // Kết quả trả về
            return result.ToString();
        }

        /// <summary>
        /// Nối mảng chuỗi với dấu phân cách 
        /// </summary>
        /// <param name="data">Mảng chuỗi</param>
        /// <param name="delimiter">Dấu phân cách</param>
        /// <returns>Chuỗi nối</returns>
        public static string JoinStringArray(string[] data, string delimiter)
        {
            // Khởi tạo biến cục bộ
            var result = new StringBuilder();
            // Diệt chuỗi trong mảng chuỗi
            foreach (var s in data) {
                // Thêm dấu phân tách
                if (!DataCheckHelper.IsNull(result.ToString())) {
                    result.Append(delimiter);
                }
                // Nỗi chuỗi
                result.Append(s);
            }
            // Kết quả trả về
            return result.ToString();
        }

        /// <summary>
        /// Tách chuỗi (Chuỗi)
        /// </summary>
        /// <param name="data">Chuỗi cần tách</param>
        /// <param name="split">Chuỗi tách</param>
        /// <returns>Danh sách chuỗi</returns>
        public static IList<string> SplitWithString(string data, string split)
        {
            // Khởi tạo biến cục bộ
            var result = new List<string>();
            var index = decimal.ToInt32(decimal.Zero);
            var strTemp = data;
            // Tìm chuổi tách
            while (true) {
                // Lấy chỉ số chuỗi tách
                index = strTemp.IndexOf(split);
                // Trường hợp không có chuỗi tách
                if (index < 0) {
                    result.Add(Trim(strTemp));
                    break;
                }
                // Gán giá trị trả về
                result.Add(Trim(strTemp.Substring(0, index + 1)));
                // Cập nhật lại chuỗi tách
                strTemp = strTemp.Substring(index + split.Length);
            }
            // Kết quả trả về
            return result;
        }
        /***** Thêm [#1] cuối *****/

        /// <summary>
        /// Trim string
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>String</returns>
        public static string Trim(string data)
        {
            return data.Trim();
        }

        /// <summary>
        /// Convert string to string
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>String</returns>
        public static string ToString(string data)
        {
            return (DataCheckHelper.IsNull(data)) ? string.Empty : data;
        }

        /***** Xóa [#1] đầu *****/
        ///// <summary>
        ///// Convert object to string
        ///// </summary>
        ///// <param name="data">Object</param>
        ///// <returns>String</returns>
        //public static string ToString(object data)
        //{
        //    return data == null ? string.Empty : data.ToString();
        //}
        //
        ///// <summary>
        ///// Convert guid to string
        ///// </summary>
        ///// <param name="data">Guid</param>
        ///// <returns>String</returns>
        //public static string ToString(Guid data)
        //{
        //    return Convert.ToString(data);
        //}
        /***** Xóa [#1] cuối *****/

        /// <summary>
        /// Replace string ("\t") to string (" ")
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>String</returns>
        public static string ToSafetyStringForTab(string data)
        {
            return data.Replace("\t", " ");
        }

        /// <summary>
        /// Convert input string
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>String</returns>
        public static string ConvertInputString(string data)
        {
            var result = Trim(ToSafetyStringForTab(ToString(data)));
            if (DataCheckHelper.IsNull(result)) {
                return null;
            }
            return result;
        }

        /// <summary>
        /// Convert input Guid
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>Guid</returns>
        public static Guid ConvertInputGuid(string data)
        {
            // Local variable declaration
            Guid result;
            // Try parse
            if (!Guid.TryParse(data, out result)) return Guid.Empty;
            // Return value
            return result;
        }

        /// <summary>
        /// Convert input number
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>Decimal?</returns>
        public static decimal? ConvertInputNumber(string data)
        {
            // Local variable declaration
            decimal result;
            var provider = Thread.CurrentThread.CurrentCulture;
            // Try parse
            if (!decimal.TryParse(data, NumberStyles.Any, provider, out result)) {
                return null;
            }
            // Return value
            return result;
        }

        /// <summary>
        /// Convert input date
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>DateTime?</returns>
        public static DateTime? ConvertInputDate(string data)
        {
            // Local variable declaration
            DateTime result;
            var provider = Thread.CurrentThread.CurrentCulture;
            // Try parse
            if (!DateTime.TryParse(data, provider, DateTimeStyles.None, out result)) {
                return null;
            }
            // Return value
            return result;
        }

        /// <summary>
        /// Convert input bool
        /// </summary>
        /// <param name="data">String</param>
        /// <returns>Boolean?</returns>
        public static bool? ConvertInputBoolean(string data)
        {
            // Local variable declaration
            bool result = false;

            // Check data
            if (!bool.TryParse(data, out result)) return null;

            // Return value
            return result;
        }

        /// <summary>
        /// Convert input stream
        /// </summary>
        /// <param name="target">Stream</param>
        /// <returns>Stream</returns>
        public static Stream ConvertInputStream(Stream data)
        {
            // Local variable declaration
            var result = Stream.Null;
            // Check data
            if (!DataCheckHelper.IsNull(data)) result = data;
            // Return value
            return result;
        }

        /***** Xóa [#1] đầu *****/
        ///// <summary>
        ///// Convert output string with format
        ///// </summary>
        ///// <param name="format">String</param>
        ///// <param name="data">String</param>
        ///// <returns>String</returns>
        //public static string ToString(string format, string data)
        //{
        //    // Local variable declaration
        //    var result = string.Empty;
        //    var provider = Thread.CurrentThread.CurrentCulture;
        //    // Check data
        //    if (!DataCheckHelper.IsNull(data)) result = data;
        //    // Return value
        //    return string.Format(provider, format, result);
        //}
        //
        ///// <summary>
        ///// Convert output number
        ///// </summary>
        ///// <param name="format">String</param>
        ///// <param name="data">Decimal</param>
        ///// <returns>String</returns>
        //public static string ToString(string format, decimal? data)
        //{
        //    // Local variable declaration
        //    var result = decimal.Zero;
        //    var provider = Thread.CurrentThread.CurrentCulture;
        //    // Check data
        //    if (!DataCheckHelper.IsNull(data)) result = data.Value;
        //    // Return value
        //    return string.Format(provider, format, result);
        //}
        //
        ///// <summary>
        ///// Convert output date
        ///// </summary>
        ///// <param name="format">String</param>
        ///// <param name="data">DateTime</param>
        ///// <returns>String</returns>
        //public static string ToString(string format, DateTime? data)
        //{
        //    // Local variable declaration
        //    var provider = Thread.CurrentThread.CurrentCulture;
        //    // Check data
        //    if (DataCheckHelper.IsNull(data)) return string.Empty;
        //    // Return value
        //    return string.Format(provider, format, data);
        //}
        //
        ///// <summary>
        ///// Convert output bool
        ///// </summary>
        ///// <param name="data">Boolean?</param>
        ///// <returns>String</returns>
        //public static string ToString(bool? data)
        //{
        //    // Check data
        //    if (DataCheckHelper.IsNull(data)) return string.Empty;
        //    // Return value
        //    return data.Value ? bool.TrueString : bool.FalseString;
        //}
        /***** Xóa [#1] cuối *****/

        /***** Thêm [#1] đầu *****/
        /// <summary>
        /// Chuyển đổi kiểu 'String' thành 'String' với định dạng
        /// </summary>
        /// <param name="format">Chuỗi định dạng</param>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(string format, string data)
        {
            // Trường hợp dữ liệu truyền vào là 'Null'
            if (DataCheckHelper.IsNull(data)) {
                return string.Empty;
            }
            // Khởi tạo biến cục bộ
            var provider = Thread.CurrentThread.CurrentCulture;
            // Kết quả trả về
            return string.Format(provider, format, data);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Decimal' thành 'String'
        /// </summary>
        /// <param name="format">Chuỗi định dạng</param>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(string format, decimal data)
        {
            // Khởi tạo biến cục bộ
            var provider = Thread.CurrentThread.CurrentCulture;
            // Kết quả trả về
            return string.Format(provider, format, data);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Decimal?' thành 'String'
        /// </summary>
        /// <param name="format">Chuỗi định dạng</param>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(string format, decimal? data)
        {
            // Trường hợp dữ liệu truyền vào là 'Null'
            if (DataCheckHelper.IsNull(data)) {
                return string.Empty;
            }
            // Kết quả trả về
            return ToString(format, data.Value);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'DateTime' thành 'String'
        /// </summary>
        /// <param name="format">Chuỗi định dạng</param>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(string format, DateTime data)
        {
            // Khởi tạo biến cục bộ
            var provider = Thread.CurrentThread.CurrentCulture;
            // Kết quả trả về
            return string.Format(provider, format, data);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'DateTime?' thành 'String'
        /// </summary>
        /// <param name="format">Chuỗi định dạng</param>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(string format, DateTime? data)
        {
            // Trường hợp dữ liệu truyền vào là 'Null'
            if (DataCheckHelper.IsNull(data)) {
                return string.Empty;
            }
            // Kết quả trả về
            return ToString(format, data.Value);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Boolean' thành 'String'
        /// </summary>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(bool data)
        {
            // Kết quả trả về
            return data ? bool.TrueString : bool.FalseString;
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Boolean?' thành 'String'
        /// </summary>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(bool? data)
        {
            // Trường hợp dữ liệu truyền vào là 'Null'
            if (DataCheckHelper.IsNull(data)) {
                return string.Empty;
            }
            // Kết quả trả về
            return ToString(data.Value);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Guid' thành 'String'
        /// </summary>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(Guid data)
        {
            // Trường hợp dữ liệu truyền vào là 'Null'
            if (DataCheckHelper.IsNull(data)) {
                return Convert.ToString(Guid.Empty);
            }
            // Kết quả trả về
            return Convert.ToString(data);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Object' thành 'String'
        /// </summary>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(object obj)
        {
            // Kết quả trả về
            return ToString(null, obj);
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Object' thành 'String'
        /// </summary>
        /// <param name="format">Chuỗi định dạng</param>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static string ToString(string format, object obj)
        {
            // Khởi tạo biến cục bộ
            var result = string.Empty;
            var strFormat = format;
            // Trường hợp đối tượng truyền vào là 'Null'
            if (obj == null) {
                return result;
            }
            // Lấy kiểu của đối tượng truyền vào
            var objType = obj.GetType();
            // Kiểm tra kiểu của đối tượng truyền vào
            if (objType == typeof(string)) {
                // Khởi tạo biến cục bộ
                var tmp = (string)obj;
                // Trường hợp chuổi định dang là 'Null'
                if (DataCheckHelper.IsNull(strFormat)) {
                    strFormat = FormatHelper.GetFormatString("FM_STRING_DEFAULT");
                }
                // Chuyển đổi kiểu 'String' thành 'String'
                result = ToString(strFormat, tmp);
            } else if (objType == typeof(decimal)) {
                // Khởi tạo biến cục bộ
                var tmp = (decimal)obj;
                // Trường hợp chuổi định dang là 'Null'
                if (DataCheckHelper.IsNull(strFormat)) {
                    strFormat = FormatHelper.GetFormatString("FM_NUMBER_DEFAULT");
                }
                // Chuyển đổi kiểu 'Decimal' thành 'String'
                result = ToString(strFormat, tmp);
            } else if (objType == typeof(decimal?)) {
                // Khởi tạo biến cục bộ
                var tmp = (decimal?)obj;
                // Trường hợp chuổi định dang là 'Null'
                if (DataCheckHelper.IsNull(strFormat)) {
                    strFormat = FormatHelper.GetFormatString("FM_NUMBER_DEFAULT");
                }
                // Chuyển đổi kiểu 'Decimal?' thành 'String'
                result = ToString(strFormat, tmp);
            } else if (objType == typeof(DateTime)) {
                // Khởi tạo biến cục bộ
                var tmp = (DateTime)obj;
                // Trường hợp chuổi định dang là 'Null'
                if (DataCheckHelper.IsNull(strFormat)) {
                    strFormat = FormatHelper.GetFormatString("FM_DATE_DEFAULT");
                }
                // Chuyển đổi kiểu 'DateTime' thành 'String'
                result = ToString(strFormat, tmp);
            } else if (objType == typeof(DateTime?)) {
                // Khởi tạo biến cục bộ
                var tmp = (DateTime?)obj;
                // Trường hợp chuổi định dang là 'Null'
                if (DataCheckHelper.IsNull(strFormat)) {
                    strFormat = FormatHelper.GetFormatString("FM_DATE_DEFAULT");
                }
                // Chuyển đổi kiểu 'DateTime?' thành 'String'
                result = ToString(strFormat, tmp);
            } else if (objType == typeof(bool)) {
                // Khởi tạo biến cục bộ
                var tmp = (bool)obj;
                // Chuyển đổi kiểu 'Boolean' thành 'String'
                result = ToString(tmp);
            } else if (objType == typeof(bool?)) {
                // Khởi tạo biến cục bộ
                var tmp = (bool?)obj;
                // Chuyển đổi kiểu 'Boolean?' thành 'String'
                result = ToString(tmp);
            } else if (objType == typeof(Guid)) {
                // Khởi tạo biến cục bộ
                var tmp = (Guid)obj;
                // Chuyển đổi kiểu 'Guid' thành 'String'
                result = ToString(tmp);
            } else {
                result = Convert.ToString(obj);
            }
            // Kết quả trả về
            return result;
        }

        /// <summary>
        /// Chuyển đổi kiểu 'Object' thành 'ExpandoObject'
        /// </summary>
        /// <param name="data">Dữ liệu cần chuyển đổi</param>
        /// <returns>Dữ liệu trả về</returns>
        public static ExpandoObject ToExpandoObject(object data)
        {
            // Khởi tạo biến cục bộ
            var result = new ExpandoObject();
            // Trường hợp dữ liệu truyền vào là 'Null'
            if (data == null) {
                return result;
            }
            // Khởi tạo danh sách kết quả
            var map = (IDictionary<string, object>)result;
            // Lấy danh sách thuộc tính của đối tượng
            var lProp = data.GetType().GetProperties().ToDictionary(p => p.Name);
            // Thêm tất cả thuộc tính của đối tượng vào danh sách kết quả
            foreach (var p in lProp) {
                map.Add(p.Key, GetProperty(data, p.Key));
            }
            // Kết quả trả về
            return result;
        }
        /***** Thêm [#1] cuối *****/

        /// <summary>
        /// Convert output decimal
        /// </summary>
        /// <param name="data">Decimal?</param>
        /// <returns>decimal</returns>
        public static decimal ToDecimal(decimal? data)
        {
            // Check data
            if (DataCheckHelper.IsNull(data)) return decimal.Zero;
            // Return value
            return data.Value;
        }

        /// <summary>
        /// Convert string to short string
        /// </summary>
        /// <param name="data">String</param>
        /// <param name="size">Int32</param>
        /// <returns>String</returns>
        public static string ToSubString(string data, int size)
        {
            // Local variable declaration
            var result = string.Empty;
            var index = int.MinValue;
            // Variable initialize
            result = Convert.ToString(data);
            // Check length
            if (result.Length < size) return data;
            // Get index word " " 
            index = result.IndexOf(" ", size, StringComparison.CurrentCulture);
            if (index < 0) index = size;
            // Convert
            return result.Substring(0, index);
        }

        /// <summary>
        /// Convert to string
        /// </summary>
        /// <param name="data">Data</param>
        /// <returns>String</returns>
        public static string ToStringWithZero(int data)
        {
            // Local variable declaration
            var result = string.Empty;

            // Variable initialize
            result = Convert.ToString(data);

            // Check month
            if (result.Length < 2) result = decimal.Zero + result;

            // Return value
            return result;
        }

        /// <summary>
        /// Convert object to ComboItem
        /// </summary>
        /// <param name="data">Data</param>
        /// <returns>ComboItem</returns>
        public static ComboItem ToComboItem(object data)
        {
            // Local variable declaration
            var item = new ComboItem();

            // Check null
            if (data == null) return item;

            // Check type
            var type = data.GetType();
            if (type != typeof(ComboItem)) return item;

            // Return value
            return (ComboItem)data;
        }

        /// <summary>
        /// Replace string
        /// </summary>
        /// <param name="data">String</param>
        /// <param name="size">Int32</param>
        /// <returns>String</returns>
        public static string Replace(string data, string oldValue, string newValue)
        {
            // Local variable declaration
            var result = Convert.ToString(data);
            // Return value
            return result.Replace(oldValue, newValue);
        }

        /// <summary>
        /// Split the string with quote.
        /// </summary>
        /// <param name="data">String</param>
        /// <param name="separator">Char</param>
        /// <returns>IList<string></returns>
        public static IList<string> SplitWithQuote(string data, char separator)
        {
            // Variable initialize
            var result = CreateList<string>();
            var index = 0;
            var start = 0;
            // Loop each character
            while (index < data.Length) {
                // Variable initialize
                var value = string.Empty;
                // Case quote
                if (data[index] == '"') {
                    // Skip initial quote
                    index++;
                    // Parse quoted value
                    start = index;
                    // Loop each character
                    while (index < data.Length) {
                        // Test for quote character
                        if (data[index] == '"') {
                            // Found one
                            index++;
                            // If two quotes together, keep one
                            // Otherwise, indicates end of value
                            if (index >= data.Length || data[index] != '"') {
                                index--;
                                break;
                            }
                        }
                        index++;
                    }
                    // Get value
                    value = data.Substring(start, index - start);
                    value = value.Replace("\"\"", "\"");
                } else { // Otherwise
                    // Parse unquoted value
                    start = index;
                    // Loop each character
                    while (index < data.Length && data[index] != separator) {
                        index++;
                    }
                    // Get value
                    value = data.Substring(start, index - start);
                }
                // Add value
                result.Add(value.Trim());
                // Go to next separator
                while (index < data.Length && data[index] != separator) {
                    index++;
                }
                // Go to next character
                if (index < data.Length) {
                    index++;
                }
            }

            // Return value
            return result;
        }

        /***** Xóa [#1] đầu *****/
        ///// <summary>
        ///// Format string
        ///// </summary>
        ///// <param name="input">String</param>
        ///// <param name="param">Object</param>
        ///// <returns>String</returns>
        //public static string FormatString(string input, object param)
        //{
        //    return FormatString(string.Empty, input, param);
        //}
        //
        ///// <summary>
        ///// Format string
        ///// </summary>
        ///// <param name="parentName">String</param>
        ///// <param name="input">String</param>
        ///// <param name="param">Object</param>
        ///// <returns>String</returns>
        //public static string FormatString(string parentName, string input, object param)
        //{
        //    // Local variable declaration
        //    var result = new StringBuilder(input);
        //    var subName = string.Empty;
        //
        //    // Get properties (param)
        //    var lParam = param.GetType().GetProperties().ToDictionary(p => p.Name);
        //    if (!string.IsNullOrEmpty(parentName)) subName = parentName + ".";
        //
        //    // Check exist
        //    foreach (var objParam in lParam) {
        //        // Get value
        //        var propName = string.Format("{{{0}{1}}}", subName, objParam.Key);
        //        var strVal = string.Empty;
        //        var propInfo = objParam.Value;
        //
        //        // Get property value
        //        var propVal = GetProperty(param, objParam.Key);
        //        // Check null
        //        if (propVal == null) continue;
        //        // Check property type
        //        if (propInfo.PropertyType == typeof(DateTime?)) {
        //            var tmp = (DateTime?)propVal;
        //            strVal = ToString(tmp);
        //        } else if (propInfo.PropertyType == typeof(decimal?)) {
        //            var tmp = (decimal?)propVal;
        //            strVal = ToString(tmp);
        //        } else if (propInfo.PropertyType == typeof(bool?)) {
        //            var tmp = (bool?)propVal;
        //            strVal = ToString(tmp);
        //        } else if (propInfo.PropertyType == typeof(Guid)) {
        //            var tmp = (Guid)propVal;
        //            strVal = ToString(tmp);
        //        } else if (propInfo.PropertyType.Namespace == "System.Collections.Generic") {
        //            var list = (IList)propVal;
        //            var startLoop = string.Format("{{Loop:{0}}}", objParam.Key);
        //            var endLoop = String.Format("{{EndLoop:{0}}}", objParam.Key);
        //            var indexStart = input.IndexOf(startLoop);
        //            var indexEnd = input.IndexOf(endLoop);
        //            var lenght = indexEnd - indexStart + endLoop.Length;
        //
        //            if (list.Count == 0) continue;
        //            if (indexStart < 0 || lenght == 0) continue;
        //
        //            var template = input.Substring(indexStart, lenght);
        //            var rsLoop = new StringBuilder();
        //            foreach (var item in list) {
        //                var tmp = template.Replace(startLoop, "").Replace(endLoop, "");
        //                rsLoop.Append(FormatString(objParam.Key, tmp, item));
        //            }
        //            propName = template;
        //            strVal = rsLoop.ToString();
        //        } else {
        //            strVal = ToString(propVal);
        //        }
        //
        //        result = result.Replace(propName, strVal);
        //    }
        //
        //    return result.ToString();
        //}
        //
        ///// <summary>
        ///// Convert data input
        ///// </summary>
        ///// <param name="source">Object</param>
        ///// <param name="target">Object</param>
        //public static void ConvertInput(object source, object target)
        //{
        //    // Check null
        //    if (source == null) return;
        //    // Get properties (source)
        //    var lSource = source.GetType().GetProperties().ToDictionary(p => p.Name);
        //    // Get properties (target)
        //    var lTarget = target.GetType().GetProperties().ToDictionary(p => p.Name);
        //    // Loop source
        //    foreach (var item in lSource) {
        //        // Check exist
        //        if (!lTarget.ContainsKey(item.Key)) continue;
        //        // Local variable declaration
        //        var s = item.Value;
        //        var t = lTarget[item.Key];
        //        // Get property value
        //        var newValue = GetProperty(source, s.Name);
        //        // Check null
        //        if (newValue == null) continue;
        //        // Check property type
        //        if (s.PropertyType != t.PropertyType) {
        //            if (t.PropertyType == typeof(DateTime?))
        //                newValue = ConvertInputDate(newValue.ToString());
        //            else if (t.PropertyType == typeof(decimal?))
        //                newValue = ConvertInputNumber(newValue.ToString());
        //            else if (t.PropertyType == typeof(bool?))
        //                newValue = ConvertInputBoolean(newValue.ToString());
        //            else if (t.PropertyType == typeof(Guid))
        //                newValue = ConvertInputGuid(newValue.ToString());
        //            else if (t.PropertyType == typeof(string))
        //                newValue = newValue.ToString();
        //            else if (t.PropertyType.IsClass) {
        //                var tmp = Activator.CreateInstance(t.PropertyType);
        //                ConvertInput(newValue, tmp);
        //                newValue = tmp;
        //            } else if (t.PropertyType.Namespace == "System.Collections.Generic") {
        //                var gt = t.PropertyType.GetGenericArguments();
        //                var gl = (IList)newValue;
        //                var rs = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(gt[0]));
        //                foreach (var gi in gl) {
        //                    var tmp = Activator.CreateInstance(gt[0]);
        //                    ConvertInput(gi, tmp);
        //                    rs.Add(tmp);
        //                }
        //                newValue = rs;
        //            } else {
        //                try {
        //                    newValue = Convert.ChangeType(newValue, t.PropertyType);
        //                } catch (Exception) {
        //                    continue;
        //                }
        //            }
        //        } else {
        //            if (t.PropertyType == typeof(string))
        //                newValue = ConvertInputString(newValue.ToString());
        //            else if (t.PropertyType == typeof(Stream))
        //                newValue = ConvertInputStream((Stream)newValue);
        //        }
        //        // Set property value
        //        try {
        //            SetProperty(target, t.Name, newValue);
        //        } catch (Exception) {
        //            continue;
        //        }
        //    }
        //}
        //
        ///// <summary>
        ///// Copy basic infomation
        ///// </summary>
        ///// <param name="source">Object</param>
        ///// <param name="target">Object</param>
        //public static void CopyBasicInfo(object source, object target)
        //{
        //    // Check null
        //    if (source == null || target == null) return;
        //
        //    // Get property (Status)
        //    var status = GetProperty(source, "Status");
        //
        //    // Set property (Status)
        //    if (status != null) {
        //        SetProperty(target, "Status", status);
        //    }
        //
        //    // Get property (CallType)
        //    var callType = GetProperty(source, "CallType");
        //
        //    // Set property (CallType)
        //    if (callType != null) {
        //        SetProperty(target, "CallType", callType);
        //    }
        //}
        //
        ///// <summary>
        ///// Copy object (T)
        ///// </summary>
        ///// <typeparam name="T">Object(T)</typeparam>
        ///// <param name="data">Object</param>
        ///// <returns>Object(T)</returns>
        //public static T CopyObject<T>(object data) where T : new()
        //{
        //    var obj = new T();
        //    if (data == null) return obj;
        //    CopyObject(data, obj);
        //    return obj;
        //}
        //
        ///// <summary>
        ///// Copy object
        ///// </summary>
        ///// <param name="source">Object</param>
        ///// <param name="target">Object</param>
        //public static void CopyObject(object source, object target)
        //{
        //    // Check null
        //    if (source == null) return;
        //    // Get properties (source)
        //    var lSource = source.GetType().GetProperties().ToDictionary(p => p.Name);
        //    // Get properties (target)
        //    var lTarget = target.GetType().GetProperties().ToDictionary(p => p.Name);
        //    // Check exist
        //    foreach (var item in lSource) {
        //        if (!lTarget.ContainsKey(item.Key)) continue;
        //        // Local variable declaration
        //        var s = item.Value;
        //        var t = lTarget[item.Key];
        //        // Get property value
        //        var newValue = GetProperty(source, s.Name);
        //        // Check null
        //        if (newValue == null) continue;
        //        // Check property type
        //        if (s.PropertyType != t.PropertyType) {
        //            if (t.PropertyType == typeof(string)) {
        //                newValue = newValue.ToString();
        //            } else if (t.PropertyType == typeof(DateTime)
        //                  || t.PropertyType == typeof(DateTime?)) {
        //                DateTime tmp;
        //                if (!DateTime.TryParse(newValue.ToString(), out tmp)) continue;
        //                newValue = tmp;
        //            } else if (t.PropertyType == typeof(decimal)
        //                  || t.PropertyType == typeof(decimal?)) {
        //                decimal tmp;
        //                if (!decimal.TryParse(newValue.ToString(), out tmp)) continue;
        //                newValue = tmp;
        //            } else if (t.PropertyType == typeof(bool)
        //                  || t.PropertyType == typeof(bool?)) {
        //                bool tmp;
        //                if (!bool.TryParse(newValue.ToString(), out tmp)) continue;
        //                newValue = tmp;
        //            } else if (t.PropertyType == typeof(Guid)) {
        //                Guid tmp;
        //                if (!Guid.TryParse(newValue.ToString(), out tmp)) continue;
        //                newValue = tmp;
        //            } else if (t.PropertyType.IsClass) {
        //                var tmp = Activator.CreateInstance(t.PropertyType);
        //                CopyObject(newValue, tmp);
        //                newValue = tmp;
        //            } else if (t.PropertyType.Namespace == "System.Collections.Generic") {
        //                var gt = t.PropertyType.GetGenericArguments();
        //                var gl = (IList)newValue;
        //                var rs = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(gt[0]));
        //                foreach (var gi in gl) {
        //                    var tmp = Activator.CreateInstance(gt[0]);
        //                    CopyObject(gi, tmp);
        //                    rs.Add(tmp);
        //                }
        //                newValue = rs;
        //            } else {
        //                try {
        //                    newValue = Convert.ChangeType(newValue, t.PropertyType);
        //                } catch (Exception) {
        //                    continue;
        //                }
        //            }
        //        }
        //        // Set property value
        //        try {
        //            SetProperty(target, t.Name, newValue);
        //        } catch (Exception) {
        //            continue;
        //        }
        //    }
        //}
        /***** Xóa [#1] cuối *****/

        /***** Thêm [#1] đầu *****/
        /// <summary>
        /// Chuyển đổi danh sách code thành ComboModel
        /// </summary>
        /// <param name="target">Danh sách code</param>
        /// <param name="selectedValue">Giá trị chọn</param>
        /// <returns>ComboModel</returns>
        public static ComboModel ToComboItems(IList<KeyValueObject> target, string selectedValue)
        {
            // Khởi tạo biến cục bộ
            var listComboItems = DataHelper.CreateList<ComboItem>();
            var comboModel = new ComboModel();
            var combo = new ComboItem();
            var val = string.Empty;
            // Diệt danh sách code
            foreach (var obj in target) {
                combo = new ComboItem();
                combo.Code = ToString(obj.Key);
                combo.Name = ToString(obj.Value);
                if (combo.Code == selectedValue
                    || (DataCheckHelper.IsNull(selectedValue)
                    && target.IndexOf(obj) == 0)) {
                    val = combo.Code;
                }
                listComboItems.Add(combo);
            }
            // Gán giá trị
            comboModel.SeletedValue = val;
            comboModel.ListItems = listComboItems;
            // Kết quả trả về
            return comboModel;
        }

        /// <summary>
        /// Sao chép đối tượng
        /// </summary>
        /// <param name="source">Đối tượng nguồn</param>
        /// <param name="target">Đối tượng đích</param>
        public static void CopyObject(object source, object target)
        {
            // Kết quả trả về
            CopyObject(source, target, CreateMap<string, string>());
        }

        /// <summary>
        /// Sao chép đối tượng với kiểu trả về là kiểu chỉ định (T)
        /// </summary>
        /// <typeparam name="T">Kiểu chỉ định (T)</typeparam>
        /// <param name="data">Đối tượng nguồn</param>
        /// <returns>Đối tượng đã sao chép (T)</returns>
        public static T CopyObject<T>(object data) where T : new()
        {
            // Kết quả trả về
            return CopyObject<T>(data, CreateMap<string, string>());
        }

        /// <summary>
        /// Sao chép đối tượng với kiểu trả về là kiểu chỉ định (T)
        /// </summary>
        /// <typeparam name="T">Kiểu chỉ định (T)</typeparam>
        /// <param name="data">Đối tượng nguồn</param>
        /// <param name="map">Danh sách chỉ định thuộc tính sao chép</param>
        /// <returns>Đối tượng đã sao chép (T)</returns>
        public static T CopyObject<T>(object data, IDictionary<string, string> map) where T : new()
        {
            // Khởi tạo đối tượng trả về
            var obj = new T();
            // Trường hợp đối tượng nguồn là 'Null'
            if (data == null) {
                return obj;
            }
            // Sao chép đối tượng với danh sách mở rộng
            CopyObject(data, obj, map);
            // Kết quả trả về
            return obj;
        }

        /// <summary>
        /// Sao chép đối tượng với danh sách mở rộng
        /// </summary>
        /// <param name="source">Đối tượng nguồn</param>
        /// <param name="target">Đối tượng đích</param>
        /// <param name="map">Danh sách chỉ định thuộc tính sao chép</param>
        public static void CopyObject(object source, object target, IDictionary<string, string> map)
        {
            // Trường hợp đối tượng nguồn là 'Null'
            if (source == null) {
                return;
            }
            // Lấy danh sách thuộc tính của đối tượng nguồn
            var lSource = source.GetType().GetProperties().ToDictionary(p => p.Name);
            // Lấy danh sách thuộc tính của đối tượng đích
            var lTarget = target.GetType().GetProperties().ToDictionary(p => p.Name);
            // Diệt các thuộc tính đối tượng nguồn
            foreach (var s in lSource) {
                // Khởi tạo biến cục bộ
                var sKey = s.Key;
                var tKey = s.Key;
                // Trường hợp có thuộc tính chỉ định
                if (map.ContainsKey(sKey)) {
                    tKey = map[sKey];
                }
                // Trường hợp không tồn tại thuộc tính đích
                if (!lTarget.ContainsKey(tKey)) {
                    continue;
                }
                // Khởi tạo biến cục bộ
                var sPro = s.Value;
                var tPro = lTarget[tKey];
                // Lấy giá trị thuộc tính nguồn
                var newValue = GetProperty(source, sPro.Name);
                // Trường hợp giá trị thuộc tính nguồn là 'Null'
                if (newValue == null) {
                    continue;
                }
                // Thay đổi kiểu cho đối tượng
                newValue = ChangeType(newValue, tPro.PropertyType);
                // Trường hợp giá trị thuộc tính nguồn là 'Null'
                if (newValue == null) {
                    continue;
                }
                // Gán giá trị thuộc tính đích
                try {
                    SetProperty(target, tPro.Name, newValue);
                } catch (Exception) {
                    continue;
                }
            }
        }

        /// <summary>
        /// Chuyển đổi kiểu cho đối tượng
        /// <para>Kết quả trả về là 'Null' nếu có phát sinh lỗi khi thay đổi kiểu (Bao gồm các kiểu không thể gán 'Null')</para>
        /// </summary>
        /// <param name="source">Đối tượng nguồn</param>
        /// <param name="type">Kiểu đối tượng trả về</param>
        /// <returns>Đối tượng đã chuyển kiểu</returns>
        public static object ChangeType(object source, Type type)
        {
            // Trường hợp đối tượng nguồn là 'Null'
            if (source == null) {
                return null;
            }
            // Khợi tạo biến cục bộ
            var sType = source.GetType();
            var tType = type;
            // Trường hợp kiểu đối tượng là 'Type'
            if (tType == Type.GetType("System.Type")
                && sType == Type.GetType("System.RuntimeType")) {
                return source;
            }
            // Khợi tạo đối tượng kết quả
            var rObj = new object();
            // Trường kiểu đối tượng trả về khác kiểu đối tượng nguồn
            if (tType != sType) {
                if (tType == typeof(DateTime)) {
                    var tmp = ConvertInputDate(source.ToString());
                    if (!tmp.HasValue) {
                        return null;
                    }
                    rObj = tmp.Value;
                } else if (tType == typeof(DateTime?)) {
                    rObj = ConvertInputDate(source.ToString());
                } else if (tType == typeof(decimal)) {
                    var tmp = ConvertInputNumber(source.ToString());
                    if (!tmp.HasValue) {
                        return null;
                    }
                    rObj = tmp.Value;
                } else if (tType == typeof(decimal?)) {
                    rObj = ConvertInputNumber(source.ToString());
                } else if (tType == typeof(bool)) {
                    var tmp = ConvertInputBoolean(source.ToString());
                    if (!tmp.HasValue) {
                        return null;
                    }
                    rObj = tmp.Value;
                } else if (tType == typeof(bool?)) {
                    rObj = ConvertInputBoolean(source.ToString());
                } else if (tType == typeof(Guid)) {
                    rObj = ConvertInputGuid(source.ToString());
                } else if (tType == typeof(string)) {
                    rObj = ToString(null, source);
                } else if (tType.IsClass && !(tType.IsAbstract || tType.IsInterface)) {
                    // Khợi tạo đối tượng đích
                    var target = Activator.CreateInstance(tType);
                    // Sao chép đối tượng
                    CopyObject(source, target);
                    // Gán giá trị trả về
                    rObj = target;
                } else if (tType.Namespace == "System.Collections.Generic") {
                    // Khợi tạo đối tượng đích
                    var gt = tType.GetGenericArguments();
                    var gl = (IList)source;
                    var rs = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(gt[0]));
                    foreach (var gi in gl) {
                        var target = Activator.CreateInstance(gt[0]);
                        CopyObject(source, target);
                        rs.Add(target);
                    }
                    // Gán giá trị trả về
                    rObj = rs;
                } else {
                    try {
                        rObj = Convert.ChangeType(source, tType);
                    } catch (Exception) {
                        return null;
                    }
                }
            } else { // Trường hợp ngược lại
                if (tType == typeof(string)) {
                    rObj = ConvertInputString(source.ToString());
                } else if (tType == typeof(Stream)) {
                    rObj = ConvertInputStream((Stream)source);
                } else {
                    rObj = source;
                }
            }
            // Kết quả trả về
            return rObj;
        }

        /// <summary>
        /// Sao chép thông tin cơ bản
        /// </summary>
        /// <param name="source">Đối tượng nguồn</param>
        /// <param name="target">Đối tượng đích</param>
        public static void CopyBasicInfo(object source, object target)
        {
            // Trường hợp đối tượng nguồn hoặc đối tượng đích là 'Null'
            if (source == null || target == null) {
                return;
            }
            // Lấy giá trị thuộc tính 'Status'
            var status = GetProperty(source, "Status");
            // Gán giá trị thuộc tính 'Status'
            if (status != null) {
                SetProperty(target, "Status", status);
            }
            // Lấy giá trị thuộc tính 'CallType'
            var callType = GetProperty(source, "CallType");
            // Gán giá trị thuộc tính 'CallType'
            if (callType != null) {
                SetProperty(target, "CallType", callType);
            }
        }

        /// <summary>
        /// Lấy danh sách thuộc tính của đối tượng
        /// </summary>
        /// <param name="obj">Đối tượng lấy</param>
        /// <returns>Danh sách thuộc tính</returns>
        public static IDictionary<string, object> GetProperties(object obj)
        {
            // Khởi tạo biến cục bộ
            var map = CreateMap<string, object>();
            // Trường hợp đối tượng là 'Null'
            if (obj == null) return map;
            // Lấy danh sách thuộc tính
            var lProp = obj.GetType().GetProperties().ToDictionary(p => p.Name);
            // Diệt thuộc tính của đối tượng
            foreach (var prop in lProp) {
                map.Add(prop.Key, GetProperty(obj, prop.Key));
            }
            // Kết quả trả về
            return map;
        }

        /// <summary>
        /// Lấy giá trị thuộc tính của đối tượng
        /// </summary>
        /// <param name="obj">Đối tượng cần lấy</param>
        /// <param name="path">Tên thuộc tính</param>
        /// <returns>Giá tị thuộc tính</returns>
        public static object GetProperty(object obj, string path)
        {
            // Khởi tạo biến cục bộ
            var result = obj;
            // Diệt các cấp thuộc tính của đối tượng
            foreach (var name in path.Split(Chars.PERIOD)) {
                // Trường hợp đối tượng là 'Null'
                if (result == null) {
                    return null;
                }
                // Trường hợp kiểu của đối tượng là 'ExpandoObject'
                if (result.GetType() == typeof(ExpandoObject)) {
                    // Lấy thông tin thuộc tính
                    var map = (IDictionary<string, object>)result;
                    // Trường hợp không tồn tại thuộc tính
                    if (!map.ContainsKey(name)) {
                        return null;
                    }
                    // Gán giá trị vào kết quả trả về
                    result = map[name];
                } else {
                    // Lấy thông tin thuộc tính
                    var prop = result.GetType().GetProperty(name);
                    // Trường hợp không tồn tại thuộc tính
                    if (prop == null) {
                        return null;
                    }
                    // Gán giá trị vào kết quả trả về
                    result = prop.GetGetMethod().Invoke(result, null);
                }
            }
            // Kết quả trả về
            return result;
        }

        /// <summary>
        /// Gán giá trị thuộc tính cho đối tượng
        /// </summary>
        /// <param name="obj">Đối tượng cần gán</param>
        /// <param name="name">Tên thuộc tính</param>
        /// <param name="val">Giá trị gán</param>
        public static void SetProperty(object obj, string name, object val)
        {
            // Trường hợp obj là null
            if (obj == null) {
                return;
            }
            // Lấy thông tin thuộc tính
            var prop = obj.GetType().GetProperty(name);
            // Trường hợp không tồn tại thuộc tính
            if (prop == null) {
                return;
            }
            // Gán giá trị thuộc tính
            prop.GetSetMethod().Invoke(obj, new[] { val });
        }

        /// <summary>
        /// Tạo đối tượng với tham số truyền vào
        /// </summary>
        /// <typeparam name="T">Kiểu đối tượng</typeparam>
        /// <param name="param">Danh sách tham số</param>
        /// <returns>Đối tượng</returns>
        public static T CreateObject<T>(params object[] param)
        {
            // Lấy kiểu đối tượng
            var type = typeof(T);
            // Kết quả trả về
            return AutoCast<T>(CreateObject(type, param));
        }

        /// <summary>
        /// Tạo đối tượng với tham số truyền vào
        /// </summary>
        /// <param name="type">Kiểu đối tượng</param>
        /// <param name="param">Danh sách tham số</param>
        /// <returns>Đối tượng</returns>
        public static object CreateObject(Type type, params object[] param)
        {
            // Trả về null trong tường hợp kiểu là null
            if (type == null) {
                return null;
            }
            // Kết quả trả về
            return Activator.CreateInstance(type, param);
        }

        /// <summary>
        /// Tạo danh sách đối tượng
        /// </summary>
        /// <typeparam name="T">Kiểu đối tượng</typeparam>
        /// <returns>Danh sách đối tượng</returns>
        public static IList<T> CreateList<T>()
        {
            // Kết quả trả về
            return new List<T>();
        }

        /// <summary>
        /// Tạo map (K,V)
        /// </summary>
        /// <returns>Map(K,V)</returns>
        public static IDictionary<K, V> CreateMap<K, V>()
        {
            // Kết quả trả về
            return new Dictionary<K, V>();
        }

        /// <summary>
        /// Ép kiểu đối tượng
        /// </summary>
        /// <typeparam name="T">Kiểu đối tượng</typeparam>
        /// <param name="src">Đối tượng cần ép kiểu</param>
        /// <returns>Đối tượng đã ếp kiểu</returns>
        public static T AutoCast<T>(object src)
        {
            // Kết quả trả về
            return (T)src;
        }
        /***** Thêm [#1] cuối *****/

        /***** Xóa [#1] đầu *****/
        ///// <summary>
        ///// Get property
        ///// </summary>
        ///// <param name="obj">Object</param>
        ///// <param name="propertyName">String</param>
        //public static object GetProperty(object obj, string propertyName)
        //{
        //    // Local variable declaration
        //    var p = obj.GetType().GetProperty(propertyName);
        //    // Check null
        //    if (p == null) return null;
        //    // Return value
        //    return p.GetGetMethod().Invoke(obj, null);
        //}

        ///// <summary>
        ///// Set property
        ///// </summary>
        ///// <param name="obj">Object</param>
        ///// <param name="propertyName">String</param>
        ///// <param name="newValue">Object</param>
        //public static void SetProperty(object obj, string propertyName, object newValue)
        //{
        //    // Local variable declaration
        //    var p = obj.GetType().GetProperty(propertyName);
        //    // Check null
        //    if (p == null) return;
        //    // Setting value
        //    p.GetSetMethod().Invoke(obj, new[] { newValue });
        //}
        //
        ///// <summary>
        ///// Create object
        ///// </summary>
        ///// <param name="t">Type</param>
        ///// <returns>Object</returns>
        //public static object CreateObject(Type t)
        //{
        //    // Check null
        //    if (t == null) return null;
        //    // Setting value
        //    return Activator.CreateInstance(t);
        //}
        //
        ///// <summary>
        ///// Create object with param
        ///// </summary>
        ///// <param name="t">Type</param>
        ///// <param name="p">Param</param>
        ///// <returns>Object</returns>
        //public static object CreateObject(Type t, object p)
        //{
        //    // Check null
        //    if (t == null) return null;
        //    // Setting value
        //    return Activator.CreateInstance(t, p);
        //}
        //
        ///// <summary>
        ///// Create a list (T)
        ///// </summary>
        ///// <returns>IList (T)</returns>
        //public static IList<T> CreateList<T>()
        //{
        //    return new List<T>();
        //}
        //
        ///// <summary>
        ///// Cast Object(T)
        ///// </summary>
        ///// <typeparam name="T">Object(T)</typeparam>
        ///// <param name="src">Object</param>
        ///// <returns>Object(T)</returns>
        //public static T AutoCast<T>(object src)
        //{
        //    return (T)src;
        //}
        /***** Xóa [#1] cuối *****/

        /// <summary>
        /// Get Md5 Hash
        /// </summary>
        /// <param name="input">String</param>
        /// <returns>String</returns>
        public static string GetMd5Hash(string input)
        {
            // Local variable declaration
            MD5 md5Hasher = MD5.Create();
            StringBuilder sBuilder = new StringBuilder();
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
            // Append string
            for (var i = 0; i < data.Length; i++) {
                sBuilder.Append(data[i].ToString("x2"));
            }
            // Return value
            return sBuilder.ToString();
        }

        /// <summary>
        /// Encrypt a string with password
        /// </summary>
        /// <param name="data">Data</param>
        /// <param name="key">Password</param>
        /// <returns>Encrypted string</returns>
        public static string Encrypt(string data, string key)
        {
            // Check data
            if (DataCheckHelper.IsNull(data)) return string.Empty;
            // Local variable declaration
            var dataArray = UTF8Encoding.UTF8.GetBytes(data);
            var hashMd5 = new MD5CryptoServiceProvider();
            var keyArray = hashMd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            // Always release the resources and flush data
            hashMd5.Clear();

            var tdes = new TripleDESCryptoServiceProvider();
            // Set the secret key for the tripleDES algorithm
            tdes.Key = keyArray;
            // Mode of operation. there are other 4 modes. We choose ECB(Electronic code Book)
            tdes.Mode = CipherMode.ECB;
            // Padding mode(if any extra byte added)
            tdes.Padding = PaddingMode.PKCS7;

            var cTransform = tdes.CreateEncryptor();
            // Transform the specified region of bytes array to resultArray
            var resultArray = cTransform.TransformFinalBlock(dataArray, 0, dataArray.Length);
            // Release resources held by TripleDes Encryptor
            tdes.Clear();
            // Return the encrypted data into unreadable string format
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

        /// <summary>
        /// Decrypt a string with password
        /// </summary>
        /// <param name="data">Data</param>
        /// <param name="key">Password</param>
        /// <returns>Decrypted string</returns>
        public static string Decrypt(string data, string key)
        {
            // Check data
            if (DataCheckHelper.IsNull(data)) return string.Empty;
            // Local variable declaration
            var dataArray = Convert.FromBase64String(data);
            var hashMd5 = new MD5CryptoServiceProvider();
            var keyArray = hashMd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            // Release any resource held by the MD5CryptoServiceProvider
            hashMd5.Clear();

            var tdes = new TripleDESCryptoServiceProvider();
            // Set the secret key for the tripleDES algorithm
            tdes.Key = keyArray;
            // Mode of operation. there are other 4 modes.
            // We choose ECB(Electronic code Book)
            tdes.Mode = CipherMode.ECB;
            //padding mode(if any extra byte added)
            tdes.Padding = PaddingMode.PKCS7;

            var cTransform = tdes.CreateDecryptor();
            var resultArray = cTransform.TransformFinalBlock(dataArray, 0, dataArray.Length);
            //Release resources held by TripleDes Encryptor
            tdes.Clear();
            //return the Clear decrypted TEXT
            return UTF8Encoding.UTF8.GetString(resultArray);
        }

        /// <summary>
        /// Get unique key
        /// </summary>
        /// <returns>String unique key</returns>
        public static string GetUniqueKey()
        {
            // Local variable declaration
            var now = DateTime.Now;
            var strUniqueKey = Convert.ToString(now.ToBinary());
            // Return value
            return GetMd5Hash(strUniqueKey);
        }

        /// <summary>
        /// Get the number of days in month
        /// </summary>
        /// <param name="month">Int32</param>
        /// <param name="year">Int32</param>
        /// <returns>Int32</returns>
        public static int GetDaysInMonth(int month, int year)
        {
            var date = new DateTime(year, month, 1);
            return date.AddMonths(1).AddDays(-1).Day;
        }

        /// <summary>
        /// Get first day of month
        /// </summary>
        /// <returns>First day of month</returns>
        public static DateTime GetFirstDayOfMonth()
        {
            // Get system date
            var currentDate = DateTime.Now;
            // Return value
            return new DateTime(currentDate.Year, currentDate.Month, 1);
        }

        /// <summary>
        /// Get first day of month
        /// </summary>
        /// <param name="data">Date</param>
        /// <returns>First day of month</returns>
        public static DateTime GetFirstDayOfMonth(DateTime data)
        {
            // Return value
            return new DateTime(data.Year, data.Month, 1);
        }

        /// <summary>
        /// Get last day of month
        /// </summary>
        /// <returns>Last day of month</returns>
        public static DateTime GetLastDayOfMonth()
        {
            // Get first day of month
            var firstDayOfMonth = GetFirstDayOfMonth();
            // Return value
            return firstDayOfMonth.AddMonths(1).AddDays(-1);
        }

        /// <summary>
        /// Get last day of month
        /// </summary>
        /// <param name="date">Date</param>
        /// <returns>Last day of month</returns>
        public static DateTime GetLastDayOfMonth(DateTime data)
        {
            // Get first day of month
            var firstDayOfMonth = GetFirstDayOfMonth(data);
            // Return value
            return firstDayOfMonth.AddMonths(1).AddDays(-1);
        }

        /// <summary>
        /// Convert IEnumerable to data table
        /// </summary>
        /// <param name="data">IEnumerable</param>
        /// <returns>Data table</returns>
        public static DataTable ToDataTable<T>(IEnumerable<T> data)
        {
            // Local variable declaration
            var dtReturn = new DataTable();
            PropertyInfo[] oProps = null;
            // Check data
            if (data == null) return dtReturn;
            // Loop data
            foreach (T rec in data) {
                // Use reflection to get property names, to create table, Only first time, others 
                if (oProps == null) {
                    oProps = ((Type)rec.GetType()).GetProperties();
                    foreach (PropertyInfo pi in oProps) {
                        var colType = pi.PropertyType;
                        if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>))) {
                            colType = colType.GetGenericArguments()[0];
                        }
                        dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                    }
                }

                var dr = dtReturn.NewRow();
                foreach (PropertyInfo pi in oProps) {
                    dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);
                }

                dtReturn.Rows.Add(dr);
            }
            return dtReturn;
        }
    }
}
